<?php
/*
 * @Author: 李明
 * @Date: 2022-01-08 10:08:34
 * @LastEditTime: 2022-01-20 17:29:43
 * @LastEditors: 李明
 * @Description:
 * @FilePath: /CRM2.0-PHP/app/Http/Controllers/AllInPay/AllInPayController.php
 * @山东壹零贰肆信息科技有限公司
 */


namespace App\Http\Controllers\AllInPay;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class AllInPayController extends Controller
{
    /**
     * @description:
     * @param {*}
     * @return {*}
     */
    public static function deal_request($head, $post_data)
    {
        // 首先对收到的密码进行Base64解码
        $repMsg_64 = $post_data['repMsg'];
        $repMsg_xml = base64_decode($repMsg_64);
        $repMsg = self::xmlToArray($repMsg_xml);
        $encryptedKey_64 = $repMsg['KeyInfo']['EncryptedKey'];
        $encryptedText_64 = $repMsg['EncryptedText'];
        $encryptedKey = base64_decode($encryptedKey_64);
        $response = self::decryptByPrivateKey($encryptedKey, '../app/Http/Controllers/AllInPay/wts-111111.pfx', '111111');
        $encryptedText = base64_decode($encryptedText_64);
        $oldReponse = $response = $response = self::decrypt($encryptedText, $response);
        //第五步,截取字符串
        $end = stripos($response, "</transaction>");
        $response = substr($response, 0, $end) . "</transaction>";
        $response = iconv("UTF-8", "gb2312//TRANSLIT", $response);
        $response = self::xmlToArray($response);
        $sign_code = $response['head']['sign_code'];
        $sep_detail = $response['response']['sep_detail'];
        $acct_detail = $response['response']['acct_detail'];
        $response['sep_detail'] = $sep_detail;
        $response['acct_detail'] = $acct_detail;
        return $response;
        // return json_decode($sep_detail);
        // $newStr = str_replace('<sign_code>' . $sign_code . '</sign_code>', '', $oldReponse);
        // $endTwo = stripos($newStr, "</transaction>");
        // $newStr = substr($newStr, 0, $endTwo) . "</transaction>";
        // $return_arr = self::xmlToArray(iconv("UTF-8", "gb2312//TRANSLIT", $newStr));
        // // dd($sign_code);
    }
    //提交数据并且验签
    public static function send_request($head, $post_data)
    {
        //        return $heads;
        // $head['processing_code'] = $heads['processing-code'][0];
        // $head['inst_id'] = $heads['inst-id'][0];
        // $head['trans_date'] = $heads['trans-date'][0];
        // $head['trans_time'] = $heads['trans-time'][0];
        // $head['ver_num'] = $heads['ver-num'][0];

        //整合head和request为xml格式
        $xml = self::generateXmlStrByArr($head, $post_data);
        //生成签名
        $privateKey = file_get_contents("../app/Http/Controllers/AllInPay/wts-111111.pfx"); //（pfx文件）
        $sign_code = self::genSign($xml, $privateKey);
        $head['sign_code'] = $sign_code;

        //整合head和request为xml格式(这次是加上sign_code的xml)
        $xml = self::generateXmlStrByArr($head, $post_data);
        //以DESede算法生成一个168位的对称密钥，使用这个密钥对报文进行加密，加密算法为DESede/ECB/PKCS5Padding；
        $message = base64_encode(self::encrypt($xml));
        //使用通联的公钥KEY加密对称密钥KEY值，加密算法为RSA/ECB/PKCS1Padding；
        $key = self::encryptByPrivateCerFile('123456789123456789123456', file_get_contents("../app/Http/Controllers/AllInPay/wts.cer"));

        //按文档格式拼接
        $str = '<STSPackage><EncryptedText>';
        $str .= $message . '</EncryptedText>';
        $str .= '<KeyInfo><ReceiverX509CertSN>';
        $str .= '9085337663476627936941607074294471704'; //通联公钥序列号
        $str .= '</ReceiverX509CertSN><EncryptedKey>';
        $str .= $key;
        $str .= '</EncryptedKey></KeyInfo></STSPackage>';
        //拼接之后的字符串base_64
        $str_64 = base64_encode($str);

        //测试地址 http://116.228.64.55:28082/AppStsWeb/service/acquireAction.action
        $url = 'http://116.228.64.55:28082/AppStsWeb/service/acquireAction.action';
        $postdata = [
            'msgPlain' => $str_64 //参数
        ];
        //发送请求
        $u_res = self::send_post($url, $postdata);
//        dd($u_res);
        //---------------------------验签---------------------------
        //第一步
        $result = base64_decode($u_res);
        //第二步，获取其中的三个值(先替换，转数组)
        $result = str_replace('<STSPackage><EncryptedText>', '', $result);
        $result = str_replace('</EncryptedText>', ',', $result);
        $result = str_replace('<KeyInfo><ReceiverX509CertSN>', '', $result);
        $result = str_replace('</ReceiverX509CertSN><EncryptedKey>', ',', $result);
        $result = str_replace('</EncryptedKey></KeyInfo></STSPackage>', '', $result);
        // dd($result);
        $result_arr = explode(',', $result);
        //         dd($result_arr);
        $encryptedText = $result_arr[0];
        $receiverX509CertSN = $result_arr[1];
        $encryptedKey = $result_arr[2];

        //第三步,先Base64解码对称密钥的密文，再用自己的私钥解密，获得原对称密钥，解密算法为RSA/ECB/PKCS1Padding；
        $encryptedKey = base64_decode($encryptedKey);
        $response = self::decryptByPrivateKey($encryptedKey, '../app/Http/Controllers/AllInPay/wts-111111.pfx', '111111');
        // dd($response);
        //第四步,再用Base64解码报文密文，再用对称密钥解密Base64解码后的报文，获得报文明文，解密算法为DESede/ECB/PKCS5Padding；
        $encryptedText = base64_decode($encryptedText);
        $oldReponse = $response = $response = self::decrypt($encryptedText, $response);
        // dd($oldReponse);
        //第五步,截取字符串
        $end = stripos($response, "</transaction>");
        $response = substr($response, 0, $end) . "</transaction>";
        $response = iconv("UTF-8", "gb2312//TRANSLIT", $response);
        $response = self::xmlToArray($response);
        $sign_code = $response['head']['sign_code'];

        $newStr = str_replace('<sign_code>' . $sign_code . '</sign_code>', '', $oldReponse);
        $endTwo = stripos($newStr, "</transaction>");
        $newStr = substr($newStr, 0, $endTwo) . "</transaction>";
        $return_arr = self::xmlToArray(iconv("UTF-8", "gb2312//TRANSLIT", $newStr));

        //第六步，SHA1withRSA验签
        $sign_code = base64_decode($sign_code);
        $response = self::verify($newStr, $sign_code, file_get_contents('../app/Http/Controllers/AllInPay/wts.cer'));

        if ($response && $return_arr['response']) {
            if (
                $return_arr['response']['resp_code'] == '0000' ||
                $return_arr['response']['resp_code'] == '1111' ||
                $return_arr['response']['resp_code'] == '1112' ||
                $return_arr['response']['resp_code'] == '4444'
            ) {
                return [true, $return_arr]; //成功
            }
            return [false, $return_arr['response']['resp_msg']];
        }
        return [false, $return_arr['response']['resp_msg']];
    }
    //整合head和request为xml格式
    static function generateXmlStrByArr($head, $request)
    {
        $str = '<?xml version="1.0" encoding="GBK"?><transaction><head>';
        $str .= self::generateStrByArray($head);
        $str .= '</head><request>';
        $str .= self::generateStrByArray($request);
        $str .= '</request></transaction>';
        return $str;
    }

    //数组转xml
    static function generateStrByArray($arr)
    {
        $str = '';
        foreach ($arr as $key => $v) {
            $str .= '<' . $key . '>' . (!is_array($v) ? $v : '['.json_encode($v).']') . '</' . $key . '>';
        }
        return $str;
    }

    //xml转数组
    static function xmlToArray($xml)
    {
        $arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $arr;
    }

    //生成 sha1WithRSA 签名
    static function genSign($toSign, $privateKey)
    {
        openssl_pkcs12_read($privateKey, $certs, "111111");
        if (!$certs) exit(0);
        $signature = '';
        openssl_sign($toSign, $signature, $certs['pkey']);
        $signature = base64_encode($signature);
        return $signature;
    }

    //DES加密
    static function encrypt($desStr)
    {
        // dd($desStr);
        $key = '123456789123456789123456';  //注意此为24位密码（对应文档168位对称秘钥）
        $desStr = self::pkcs5Pad($desStr, 8);
        // dd($desStr);
        if (strlen($desStr) % 8) {
            $desStr = str_pad($desStr, strlen($desStr) + 8 - strlen($desStr) % 8, "\0");
        }
        $method = 'DES-EDE3';

        return openssl_encrypt($desStr, $method, $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, '');
    }

    //公钥加密
    static function encryptByPrivateCerFile($data, $cerFile)
    {
        $crypted = "";
        //公钥加密
        openssl_public_encrypt($data, $crypted, $cerFile);

        return base64_encode($crypted);
    }

    //RSA解密
    static function decryptByPrivateKey($data, $privateCer, $password)
    {
        $certs = [];
        openssl_pkcs12_read(file_get_contents($privateCer), $certs, $password);

        if (!$certs) return;
        $decryptedTemp = '';
        openssl_private_decrypt($data, $decryptedTemp, $certs['pkey']); //私钥解密

        return $decryptedTemp;
    }

    //pkcs5Pad
    static function pkcs5Pad($text, $len = 8)
    {
        $pad = $len - (strlen($text) % $len);
        return $text . str_repeat(chr($pad), $pad);
    }

    //解密算法
    static function decrypt($str, $key)
    {
        $method = 'DES-EDE3';

        $str = openssl_decrypt($str, $method, $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, '');

        return $str;
    }

    //公钥验签
    static function verify($sign_str, $sign, $public_key, $signature_alg = OPENSSL_ALGO_SHA1)
    {
        $public_key = openssl_get_publickey($public_key);
        $verify = openssl_verify($sign_str, $sign, $public_key, $signature_alg);
        // openssl_free_key($public_key);
        return $verify; //false or true
    }

    //发送请求
    static function send_post($url, $post_data)
    {
        $postdata = http_build_query($post_data);
        $options = array(
            'http' => array(
                'method' => 'POST',
                'header' => 'Content-type:application/x-www-form-urlencoded',
                'content' => $postdata,
                'timeout' => 15 * 60 // 超时时间（单位:s）
            )
        );
        // dd($options);
        $context = stream_context_create($options);
        //         dd($context);
        $result = file_get_contents($url, false, $context);
        return $result;
    }
}
/*
机构编码：81370000
银行编码：03040000(华夏银行)
卡bin规则：123455+13位数字且不以9结尾
分账机构结算账户：8137000081370000

普通交易统一访问地址：http://116.228.64.55:28082/AppStsWeb/service/acquireAction.action
统一单笔查询地址：http://116.228.64.55:28082/ccdp-acquire-web/service/acquireAction.action
对账文件联机下载:http://116.228.64.55:28082/ccdp-acquire-web/service/orgDownloadReconFile.action
批量交易查询:http://116.228.64.55:28082/ccdp-acquire-web/service/batchTxQuery.action
批量还款:http://116.228.64.55:28082/ccdp-acquire-web/service/batchRepaymentFileUploadAction.action
批量还款回盘文件下载:http://116.228.64.55:28082/ccdp-acquire-web/service/batchRepaymentFileDownloadAction.action
批量购买：http://116.228.64.55:28082/ccdp-acquire-web/service/batchPurchaseFileUploadAction.action
批量购买回盘下载：http://116.228.64.55:28082/ccdp-acquire-web/service/batchPurchaseFileDownloadAction.action
批量开户：http://116.228.64.55:28082/ccdp-acquire-web/service/batchSignTxFileUploadAction.action
批量开户回盘下载：http://116.228.64.55:28082/ccdp-acquire-web/service/batchSignTxFileDownloadAction.action

机构服务网站地址：
http://116.228.64.55:28082/sts-instweb/
机构服务平台用户名   admin
密码   111111
*/
